﻿using EOSDigital.API;
using EOSDigital.SDK;
using LogLib;
using MetroFramework.Forms;
using NewCapturerDemo.DSLR;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace NewCapturerDemo
{
    public partial class FormDSLRCameraSetting : MetroForm
    {
        private CanonDSLRCamera _camera;
        private EvfDataSet _evfDataSet;
        private object ErrLock = new object();
        private int ErrCount;

        private Dictionary<PropertyID, ComboBox> _comboxes;

        public FormDSLRCameraSetting(CanonDSLRCamera capture)
        {
            InitializeComponent();
            InitData();
            _camera = capture;
            _camera.MainCamera.PropertyChanged += this.MainCamera_PropertyChanged;
            RefreshCameraProperty();            
        }

        private int GetCameraIntValue(PropertyID propID, string strValue)
        {
            int result = 0;
            switch (propID)
            {
                case PropertyID.AEMode:
                    result = AEModeValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.Av:
                    result = AvValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.Tv:
                    result = TvValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.ISO:
                    result = ISOValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.WhiteBalance:
                    result = WhiteBalanceValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.ImageQuality:
                    result = ImageQualityValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.MeteringMode:
                    result = MeteringModeValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.ExposureCompensation:
                    result = ExpCompValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.PictureStyle:
                    result = PictureStyleValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.Evf_AFMode:
                    result = EvfAfModeValues.GetValue(strValue).IntValue;
                    break;
                case PropertyID.AFMode:
                    result = AfModeValues.GetValue(strValue).IntValue;
                    break;
            }
            return result;
        }

        private void ucComboxProperty_SelectedChangedEvent(object sender, EventArgs e)
        {
            ComboBox combo = sender as ComboBox;
            PropertyID key = this._comboxes.First((KeyValuePair<PropertyID, ComboBox> p) => p.Value == combo).Key;
            ComboBoxItem comboBoxItem = combo.SelectedItem as ComboBoxItem;
            this._camera.MainCamera.SetSetting(key, this.GetCameraIntValue(key, comboBoxItem.Value), 0);
        }

        private void InitSimpleUCCombox(ComboBox comBox, string str)
        {
            this.InitUCCombox(comBox, new string[1]
            {
                str
            });
        }

        private void InitUCCombox(ComboBox comBox, string[] strArray)
        {
            //List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
            comBox.Items.Clear();
            foreach (string text in strArray)
            {
                //list.Add(new KeyValuePair<string, string>(text, text));
                comBox.Items.Add(new ComboBoxItem(text,text));
            }
            //comBox.DataSource = list;
            //if (list.Count > 0)
            //{
            //    comBox.SelectedIndex = 0;
            //}
        }

        private void InitSettingCombobox(ComboBox comBox, PropertyID propID)
        {
            CameraValue[] settingsList = this._camera.MainCamera.GetSettingsList(propID);
            comBox.Enabled = (settingsList.Length != 0);
            string[] strArray = (from x in settingsList
                                 select x.StringValue).ToArray();
            this.InitUCCombox(comBox, strArray);
        }
        
        private void ComboBoxSelectValue(ComboBox cmb,string value)
		{
            int selectIndex = -1;
            for(int i = 0; i < cmb.Items.Count; i++)
			{
                ComboBoxItem item = cmb.Items[i] as ComboBoxItem;
                if(item.Value == value)
				{
                    selectIndex = i;
                    break;
				}
			}

			if (selectIndex != -1)
			{
                cmb.SelectedIndex = selectIndex;
			}
		}
        private void PropertyChangeHandler(PropertyID propID)
        {
            if (base.InvokeRequired)
            {
                base.BeginInvoke(new Action<PropertyID>(this.PropertyChangeHandler), propID);
            }
            else
            {
                Console.WriteLine("Camera States Change:" + Enum.GetName(typeof(PropertyID), propID));
                ComboBox uCCombox = null;
                if (this._comboxes.ContainsKey(propID))
                {
                    uCCombox = this._comboxes[propID];
                    uCCombox.SelectedIndexChanged -= this.ucComboxProperty_SelectedChangedEvent;
                }
                if (this._camera.MainCamera != null)
                {
                    switch (propID)
                    {
                        case PropertyID.AEMode:
                            {
                                int int32Setting2 = this._camera.MainCamera.GetInt32Setting(propID, 0);
                                string stringValue = AEModeValues.GetValue(int32Setting2).StringValue;
                                cmbPropertyAEMode.Text = stringValue;
                                break;
                            }
                        case PropertyID.AFMode:
                            {
                                int int32Setting2 = this._camera.MainCamera.GetInt32Setting(propID, 0);
                                string stringValue = AfModeValues.GetValue(int32Setting2).StringValue;
                                this.InitSimpleUCCombox(this.cmbAFMode, stringValue);
                                this.cmbAFMode.Enabled = false;
                                //this.RefreshZoomFocusStatus();
                                break;
                            }
                        case PropertyID.ImageQuality:
                        case PropertyID.WhiteBalance:
                        case PropertyID.ISO:
                        case PropertyID.MeteringMode:
                        case PropertyID.Av:
                        case PropertyID.Tv:
                        case PropertyID.ExposureCompensation:
                            this.InitSettingCombobox(uCCombox, propID);
                            if (uCCombox != null)
                            {
                                ComboBoxSelectValue(uCCombox, this.GetCameraStringValue(propID, this._camera.MainCamera.GetInt32Setting(propID, 0)));
                                //uCCombox.SelectedValue = this.GetCameraStringValue(propID, this._camera.MainCamera.GetInt32Setting(propID, 0));                                
                            }
                            break;
                        case PropertyID.Evf_AFMode:
                            this.InitSettingCombobox(uCCombox, propID);
                            if (uCCombox != null)
                            {
                                ComboBoxSelectValue(uCCombox, this.GetCameraStringValue(propID, this._camera.MainCamera.GetInt32Setting(propID, 0)));
                                //uCCombox.SelectedValue = this.GetCameraStringValue(propID, this._camera.MainCamera.GetInt32Setting(propID, 0));
                            }
                            //this.RefreshZoomFocusStatus();
                            break;
                        case PropertyID.PictureStyle:
                            {
                                this.InitSettingCombobox(uCCombox, propID);
                                if (uCCombox != null)
                                {
                                    //uCCombox.SelectedValue = this.GetCameraStringValue(propID, this._camera.MainCamera.GetInt32Setting(propID, 0));
                                    ComboBoxSelectValue(uCCombox, this.GetCameraStringValue(propID, this._camera.MainCamera.GetInt32Setting(propID, 0)));
                                }
                                PictureStyleDesc structSetting = this._camera.MainCamera.GetStructSetting<PictureStyleDesc>(PropertyID.PictureStyleDesc, 0);
                                this.txbPictureStyleDesc.Text = structSetting.ToString();
                                break;
                            }
                        case PropertyID.LensName:
                            {
                                string stringSetting = this._camera.MainCamera.GetStringSetting(PropertyID.LensName, 0);
                                this.txbLensName.Text = stringSetting;
                                break;
                            }
                        case PropertyID.AvailableShots:
                            {
                                int int32Setting = this._camera.MainCamera.GetInt32Setting(PropertyID.AvailableShots, 0);
                                this.txbAvailableShots.Text = string.Format("{0}", int32Setting);
                                break;
                            }
                        case PropertyID.FocusInfo:
                            this._evfDataSet.FocusInfo = this._camera.MainCamera.GetStructSetting<FocusInfo>(PropertyID.FocusInfo, 0);
                            break;
                    }
                    if (uCCombox != null)
                    {
                        uCCombox.SelectedIndexChanged += this.ucComboxProperty_SelectedChangedEvent;
                    }
                }
            }
        }       

        private string GetCameraStringValue(PropertyID propID, int intValue)
        {
            string result = "";
            switch (propID)
            {
                case PropertyID.AEMode:
                    result = AEModeValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.Av:
                    result = AvValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.Tv:
                    result = TvValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.ISO:
                    result = ISOValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.WhiteBalance:
                    result = WhiteBalanceValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.ImageQuality:
                    result = ImageQualityValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.MeteringMode:
                    result = MeteringModeValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.ExposureCompensation:
                    result = ExpCompValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.PictureStyle:
                    result = PictureStyleValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.Evf_AFMode:
                    result = EvfAfModeValues.GetValue(intValue).StringValue;
                    break;
                case PropertyID.AFMode:
                    result = AfModeValues.GetValue(intValue).StringValue;
                    break;
            }
            return result;
        }

        private void RefreshCameraProperty()
        {
            this.PropertyChangeHandler(PropertyID.AEMode);
            this.PropertyChangeHandler(PropertyID.Av);
            this.PropertyChangeHandler(PropertyID.Tv);
            this.PropertyChangeHandler(PropertyID.ISO);
            this.PropertyChangeHandler(PropertyID.WhiteBalance);
            this.PropertyChangeHandler(PropertyID.ImageQuality);
            this.PropertyChangeHandler(PropertyID.MeteringMode);
            this.PropertyChangeHandler(PropertyID.ExposureCompensation);
            this.PropertyChangeHandler(PropertyID.PictureStyle);
            this.PropertyChangeHandler(PropertyID.LensName);
            this.PropertyChangeHandler(PropertyID.Evf_AFMode);
            this.PropertyChangeHandler(PropertyID.AvailableShots);
            this.PropertyChangeHandler(PropertyID.AFMode);
        }

        private void MainCamera_PropertyChanged(EOSDigital.API.Camera sender, PropertyEventID eventID, PropertyID propID, int parameter)
        {
            try
            {
                if (eventID == PropertyEventID.PropertyChanged || eventID == PropertyEventID.All)
                {
                    this.PropertyChangeHandler(propID);
                }
            }
            catch (Exception ex)
            {
                this.ReportError(ex.Message, false);
            }
        }

        private void ReportError(string message, bool lockdown)
        {
            int num = default(int);
            lock (this.ErrLock)
            {
                num = ++this.ErrCount;
            }
            if (lockdown)
            {
                this.EnableUI(false);
            }
            if (num < 4)
            {
                MessageBox.Show(message);
            }
            else if (num == 4)
            {
                MessageBox.Show("Many errors happened!");
            }
            lock (this.ErrLock)
            {
                this.ErrCount--;
            }
        }

        private void EnableUI(bool enable)
        {
            if (base.InvokeRequired)
            {
                base.Invoke((Action)delegate
                {
                    this.EnableUI(enable);
                });
            }
            else
            {
                //是否允许参数设置
                cmbPropertyAEMode.Enabled = enable;
                cmbPropertyAv.Enabled = enable;
                cmbPropertyExposureCompensation.Enabled = enable;
                cmbPropertyImageQuality.Enabled = enable;
                cmbPropertyISO.Enabled = enable;
                cmbPropertyMeteringMode.Enabled = enable;
                cmbPropertyPictureStyle.Enabled = enable;
                cmbPropertyTv.Enabled = enable;
                cmbPropertyWhiteBalance.Enabled = enable;                
            }
        }

        private void InitData()
		{
            this._comboxes = new Dictionary<PropertyID, ComboBox>
            {
                {
                    PropertyID.AEMode,
                    this.cmbPropertyAEMode
                },
                {
                    PropertyID.Tv,
                    this.cmbPropertyTv
                },
                {
                    PropertyID.Av,
                    this.cmbPropertyAv
                },
                {
                    PropertyID.ISO,
                    this.cmbPropertyISO
                },
                {
                    PropertyID.WhiteBalance,
                    this.cmbPropertyWhiteBalance
                },
                {
                    PropertyID.ImageQuality,
                    this.cmbPropertyImageQuality
                },
                {
                    PropertyID.MeteringMode,
                    this.cmbPropertyMeteringMode
                },
                {
                    PropertyID.ExposureCompensation,
                    this.cmbPropertyExposureCompensation
                },
                {
                    PropertyID.PictureStyle,
                    this.cmbPropertyPictureStyle
                },
                {
                    PropertyID.Evf_AFMode,
                    this.cmbEvfAFMode
                }
            };
        }

       

        /// <summary>
        /// 保存相机参数到文件
        /// </summary>
        private void SaveSettings()
        {
            DslrProperties properties = new DslrProperties();
            properties[PropertyID.Tv].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.Tv, 0);
            properties[PropertyID.Av].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.Av, 0);
            properties[PropertyID.ISO].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.ISO, 0);
            properties[PropertyID.WhiteBalance].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.WhiteBalance, 0);
            properties[PropertyID.ImageQuality].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.ImageQuality, 0);
            properties[PropertyID.Evf_AFMode].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.Evf_AFMode, 0);
            properties[PropertyID.MeteringMode].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.MeteringMode, 0);
            properties[PropertyID.PictureStyle].Value = this._camera.MainCamera.GetInt32Setting(PropertyID.PictureStyle, 0);
            properties.SaveCurrCamPropValue();
        }

        private void FormCameraSetting_Load(object sender, EventArgs e)
        {
            Log.AddBeginningBoundary();
            Log.WriteAsync("Enter 相机参数设置");
            Log.WriteAsync("设置前的相机参数为:");           
        }
        

        private void buttonCancell_Click(object sender, EventArgs e)
        {
            this.Close();
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            SaveSettings();         
            Log.WriteAsync("设置后的相机参数为:");
            //string[] strArray = properties.StringValues();
            //foreach (string item in strArray)
            //{
            //    Log.WriteAsync(item);
            //}
            Log.WriteAsync("End 相机参数设置");
            Log.AddEndingBoundary();    
            this.Close();
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

		private void FormDSLRCameraSetting_FormClosed(object sender, FormClosedEventArgs e)
		{
                _camera.MainCamera.PropertyChanged -= this.MainCamera_PropertyChanged;
        }
	}
}
